/*
 * To change this template, choose Tools | Templates
 * and open the template in the editor.
 */
package dca.sistemascontrole.view.grafico;

import dca.sistemascontrole.domain.DataObject;
import java.awt.BorderLayout;
import java.awt.Color;
import java.awt.geom.Point2D;
import java.awt.geom.Rectangle2D;
import java.util.Calendar;
import java.util.Date;
import java.util.List;
import java.util.concurrent.locks.Lock;
import java.util.concurrent.locks.ReentrantLock;
import javax.swing.JPanel;
import org.jfree.chart.ChartFactory;
import org.jfree.chart.ChartMouseEvent;
import org.jfree.chart.ChartMouseListener;
import org.jfree.chart.ChartPanel;
import org.jfree.chart.JFreeChart;
import org.jfree.chart.axis.ValueAxis;
import org.jfree.chart.plot.XYPlot;
import org.jfree.chart.renderer.xy.XYItemRenderer;
import org.jfree.data.time.FixedMillisecond;
import org.jfree.data.time.TimeSeries;
import org.jfree.data.time.TimeSeriesCollection;
import org.jfree.data.time.TimeSeriesDataItem;
import org.jfree.data.xy.XYDataset;
import org.jfree.ui.RectangleInsets;

/**
 *
 * @author Rafael
 */
public class GraficoTensao extends JPanel {

    private XYPlot xyplot;
    private XYPlot xyplotNivel;
    private ChartPanel pnlChart;
    private TimeSeries timeSeriesUSaturado;
    private TimeSeries timeSeriesU;
    private TimeSeries timeSeriesUp;
    private TimeSeries timeSeriesUd;
    private TimeSeries timeSeriesUi;
    private TimeSeriesCollection timeSeriesCollection;
    private long maximunVisiblePeriod;
    private Lock lock = new ReentrantLock();

    public GraficoTensao() {
        this("", "", "", GraphicPanel.DEFAULT_MAXIMUN_VISIBLE_PERIOD);
    }

    public GraficoTensao(long maximunVisibleWindow) {
        this("", "", "", maximunVisibleWindow);
    }

    public GraficoTensao(String title, String timeAxisLabel, String valueAxisLabel, long maximunVisibleWindow) {
        this.maximunVisiblePeriod = maximunVisibleWindow;

        setLayout(new BorderLayout());
        timeSeriesUSaturado = new TimeSeries("Controle Saturado");
        timeSeriesUSaturado.removeAgedItems(true);
        timeSeriesU = new TimeSeries("Controle");
        timeSeriesU.removeAgedItems(true);
        timeSeriesUi = new TimeSeries("Controle Integrativo");
        timeSeriesUi.removeAgedItems(true);
        timeSeriesUd = new TimeSeries("Controle Derivativo");
        timeSeriesUd.removeAgedItems(true);
        timeSeriesUp = new TimeSeries("Controle Proporcional");
        timeSeriesUp.removeAgedItems(true);

        timeSeriesCollection = new TimeSeriesCollection();
        timeSeriesCollection.addSeries(timeSeriesUSaturado);
        timeSeriesCollection.addSeries(timeSeriesU);
        timeSeriesCollection.addSeries(timeSeriesUi);
        timeSeriesCollection.addSeries(timeSeriesUd);
        timeSeriesCollection.addSeries(timeSeriesUp);

        JFreeChart jfreechart = createChart(timeSeriesCollection, title, timeAxisLabel, "(V)");
        pnlChart = new ChartPanel(jfreechart);
        pnlChart.setBackground(new Color(247, 247, 247));
        pnlChart.setVisible(true);
        add(pnlChart, BorderLayout.CENTER);
    }

    public void addValue(double uSaturado, double u, double ui, double up, double ud, FixedMillisecond time) {
        try {
            lock.lock();
            TimeSeriesDataItem seriesDataItemUSaturado = new TimeSeriesDataItem(time, uSaturado);
            TimeSeriesDataItem seriesDataItemUp = new TimeSeriesDataItem(time, up);
            TimeSeriesDataItem seriesDataItemUi = new TimeSeriesDataItem(time, ui);
            TimeSeriesDataItem seriesDataItemUd = new TimeSeriesDataItem(time, ud);
            TimeSeriesDataItem seriesDataItemU = new TimeSeriesDataItem(time, u);

            timeSeriesUSaturado.addOrUpdate(seriesDataItemUSaturado);
            timeSeriesUp.addOrUpdate(seriesDataItemUp);
            timeSeriesUi.addOrUpdate(seriesDataItemUi);
            timeSeriesUd.addOrUpdate(seriesDataItemUd);
            timeSeriesU.addOrUpdate(seriesDataItemU);

            pnlChart.revalidate();
            pnlChart.repaint();
        } finally {
            lock.unlock();
        }
    }

    public void clear() {
        timeSeriesUSaturado.clear();
        timeSeriesUp.clear();
        timeSeriesUd.clear();
        timeSeriesUi.clear();
        timeSeriesU.clear();
    }

    private JFreeChart createChart(XYDataset xydataset, String title, String timeAxisLabel, String valueAxisLabel) {
        JFreeChart jfreechart = ChartFactory.createTimeSeriesChart(title, timeAxisLabel, valueAxisLabel, xydataset, true, true, false);
        xyplot = (XYPlot) jfreechart.getPlot();

        xyplot.setBackgroundPaint(Color.white);
        xyplot.setDomainGridlinePaint(Color.gray);
        xyplot.setRangeGridlinePaint(Color.gray);
        xyplot.setOutlineVisible(false);
        xyplot.setInsets(new RectangleInsets(0, 5, 5, 0));

        xyplot.setDomainPannable(true);
        xyplot.setRangePannable(false);
        xyplot.setDomainCrosshairVisible(true);
        xyplot.setRangeCrosshairVisible(true);

        XYItemRenderer renderer = xyplot.getRenderer();
        renderer.setSeriesPaint(0, Color.RED);
        renderer.setSeriesPaint(1, Color.BLUE);
        renderer.setSeriesPaint(2, Color.GREEN);
        renderer.setSeriesPaint(3, Color.BLACK);
        renderer.setSeriesPaint(4, Color.PINK);

//        NumberAxis range = (NumberAxis) xyplot.getRangeAxis();
//        range.setRange(-10.00, 10.00);

        ValueAxis valueaxis = xyplot.getDomainAxis();
        valueaxis.setAutoRange(true);
        valueaxis.setFixedAutoRange(GraphicPanel.DEFAULT_MAXIMUN_VISIBLE_PERIOD);

        jfreechart.setBackgroundPaint(Color.WHITE);

        return jfreechart;
    }

    public long getMaximunVisiblePeriod() {
        return maximunVisiblePeriod;
    }

    public void setMaximunVisiblePeriod(long maximunVisiblePeriod) {
        this.maximunVisiblePeriod = maximunVisiblePeriod;
    }

    public void setValues(List<DataObject> uSaturado, List<DataObject> u, List<DataObject> up, List<DataObject> ui, List<DataObject> ud) {
        for (DataObject dataObject : uSaturado) {
            timeSeriesUSaturado.addOrUpdate(dataObject.getMillisecond(), dataObject.getValue());
        }

        for (DataObject dataObject : u) {
            timeSeriesU.addOrUpdate(dataObject.getMillisecond(), dataObject.getValue());
        }

        for (DataObject dataObject : up) {
            timeSeriesUp.addOrUpdate(dataObject.getMillisecond(), dataObject.getValue());
        }

        for (DataObject dataObject : ui) {
            timeSeriesUi.addOrUpdate(dataObject.getMillisecond(), dataObject.getValue());
        }

        for (DataObject dataObject : ud) {
            timeSeriesUd.addOrUpdate(dataObject.getMillisecond(), dataObject.getValue());
        }
    }

    public void exibirUSaturado(boolean exibir) {
        if (exibir) {
            List series = timeSeriesCollection.getSeries();
            if (!series.contains(timeSeriesUSaturado)) {
                timeSeriesCollection.addSeries(timeSeriesUSaturado);
            }
        } else {
            timeSeriesCollection.removeSeries(timeSeriesUSaturado);
        }
    }

    public void exibirU(boolean exibir) {
        if (exibir) {
            List series = timeSeriesCollection.getSeries();
            if (!series.contains(timeSeriesU)) {
                timeSeriesCollection.addSeries(timeSeriesU);
            }
        } else {
            timeSeriesCollection.removeSeries(timeSeriesU);
        }
    }

    public void exibirUi(boolean exibir) {
        if (exibir) {
            List series = timeSeriesCollection.getSeries();
            if (!series.contains(timeSeriesUi)) {
                timeSeriesCollection.addSeries(timeSeriesUi);
            }
        } else {
            timeSeriesCollection.removeSeries(timeSeriesUi);
        }
    }

    public void exibirUp(boolean exibir) {
        if (exibir) {
            List series = timeSeriesCollection.getSeries();
            if (!series.contains(timeSeriesUp)) {
                timeSeriesCollection.addSeries(timeSeriesUp);
            }
        } else {
            timeSeriesCollection.removeSeries(timeSeriesUp);
        }
    }

    public void exibirUd(boolean exibir) {
        if (exibir) {
            List series = timeSeriesCollection.getSeries();
            if (!series.contains(timeSeriesUd)) {
                timeSeriesCollection.addSeries(timeSeriesUd);
            }
        } else {
            timeSeriesCollection.removeSeries(timeSeriesUd);
        }
    }

    public XYPlot getXyplot() {
        return xyplot;
    }

    public void setXyplotNivel(XYPlot xyplotNivel) {
        this.xyplotNivel = xyplotNivel;
    }
}
